package cn.lzm.server;

import cn.hutool.json.JSONUtil;
import cn.lizemin.entity.RpcRequest;
import cn.lizemin.entity.RpcResponse;
import cn.lzm.RpcApplication;
import cn.lzm.registry.LocalRegistry;
import cn.lzm.serializer.Serializer;
import cn.lzm.serializer.SerializerFactoryV2;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author lzm
 * @Date 2024/7/16
 * @description http请求处理器
 */
public class HttpServerHandler implements Handler<HttpServerRequest> {

    private static final Serializer SERIALIZER;

    static {
        // 改为使用配置文件中定义的序列化方式
        String serializerName = RpcApplication.getRpcConfig().getSerializer();
        SERIALIZER = SerializerFactoryV2.getSerializer(serializerName);
    }

    @Override
    public void handle(HttpServerRequest req) {
        System.out.printf("接收到请求：%s %s,\n", req.method(), req.uri());
        // 反序列化
        req.bodyHandler(body -> {
            byte[] bytes = body.getBytes();
            RpcRequest param = SERIALIZER.deserialize(bytes, RpcRequest.class);
            System.out.printf("接收到的请求参数为：%s\n", JSONUtil.toJsonStr(param));
            RpcResponse resp = new RpcResponse();
            if (Objects.isNull(param)) {
                resp.setMessage("请求参数为null");
                doResponse(req, resp);
                return;
            }
            String serviceName = param.getServiceName();
            // 这里是通过本地配置中心拿到的处理器，这里也许应该换成配置中心？
            // 不对，这里存放的是接口-实现类，而注册中心放的是服务名：服务节点列表，这两者的功能定位并不相同
            Class<?> service = LocalRegistry.get(serviceName);
            String methodName = param.getMethodName();
            Class<?>[] argTypes = param.getArgTypes();
            try {
                Object target = service.newInstance();
                Method method = service.getDeclaredMethod(methodName, argTypes);
                Object[] args = param.getArgs();
                Object result = method.invoke(target, args);
                resp.setMessage("请求成功");
                resp.setData(result);
                resp.setDataType(result.getClass());
                doResponse(req, resp);
            } catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
                     InvocationTargetException e) {
                throw new RuntimeException(e);
            }


        });

    }

    private void doResponse(HttpServerRequest req, RpcResponse resp) {
        byte[] data = SERIALIZER.serialize(resp);
        req.response()
                .putHeader("content-type", "application/json; charset=utf-8")
                .end(Buffer.buffer(data));
    }

}
